package com.stylefeng.guns.rest.modular.App.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.model.Pager;
import com.stylefeng.guns.rest.Tools.CodeMsg;
import com.stylefeng.guns.rest.Tools.Result;
import com.stylefeng.guns.rest.common.annotion.SSO;
import com.stylefeng.guns.rest.modular.App.model.OrderInf;
import com.stylefeng.guns.rest.modular.App.service.IOrderInfService;
import com.stylefeng.guns.rest.modular.DTO.ComplaintDTO;
import com.stylefeng.guns.rest.modular.DTO.PayVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.StampedLock;

/**
 * 线路类型
 *
 * @author sasazaixian
 * @Date 2018-11-15 14:16
 */
@Controller
@RequestMapping(value = {"/gunsApi/auth/orderInf"})
@Api(value = "任务订单相关api", tags = {"任务订单相关接口"})
@Log4j2
public class OrderInfController extends BaseController {
    @Autowired
    private IOrderInfService orderInfService;
    @Value("${spring.bgServerUrl}")
    private String bgServerUrl;
    /**
     * 订单生成的机器 IP
     */
    @Value("${weifutong.refund_url}")
    private String REFUND_URL;
    @Value("${weifutong.refund_method}")
    private String method;
    /**
     * 订单操作锁
     */
    private final StampedLock stampedLock = new StampedLock();




    /**
     * 获取任务详情
     *
     * @param orderInf
     * @return
     */
    @ApiOperation(value = "获取任务详情", notes = "获取任务详情", httpMethod = "POST")
    @PostMapping(value = "/selectListTaskOrder", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    @SSO
    public Result selectListTaskOrder(@RequestBody @ApiParam(name = "orderInf", value = "线路类型对象") OrderInf orderInf) {
        try {
            return Result.success(orderInfService.selectListOrderInf(orderInf, getToken()));
        } catch (Exception e) {
            return Result.error("获取任务详情列表失败!", 500100);
        }
    }

    /**
     * 上车
     *
     * @param tiId   任务单ID
     * @param oiId   订单id
     * @param qrcode 乘车码
     * @param addr   上车地址
     * @param pos    上车经纬度
     * @return
     */
    @ApiOperation(value = "乘客上车", notes = "乘客上车", httpMethod = "POST")
    @PostMapping(value = "/upCar", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    @SSO
    public Result upCar(
            @ApiParam(name = "tiId", value = "任务ID", required = true) @RequestParam(value = "tiId") String tiId,
            @ApiParam(name = "oiId", value = "订单Id", required = true) @RequestParam(value = "oiId") String oiId,
            @ApiParam(name = "qrcode", value = "乘车码", required = true) String qrcode,
            @ApiParam(name = "addr", value = "地址", required = true) @RequestParam(value = "addr") String addr,
            @ApiParam(name = "pos", value = "经纬度", required = true) @RequestParam(value = "pos") String pos) {
        try {
            return Result.success(orderInfService.updateOrderInfUp(tiId, oiId, qrcode, addr, pos, getToken()));
        } catch (Exception e) {
            return Result.error(e.getMessage(), 500100);
        }
    }


    /**
     * 下车
     *
     * @param tiId 任务单ID
     * @param oiId 订单id
     * @param addr 下车地址
     * @param pos  下车经纬度
     * @return
     */
    @ApiOperation(value = "乘客下车", notes = "乘客下车", httpMethod = "POST")
    @PostMapping(value = "/downCar", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    @SSO
    public Result downCar(
            @ApiParam(name = "tiId", value = "任务ID", required = true) @RequestParam(value = "tiId") String tiId,
            @ApiParam(name = "oiId", value = "订单Id", required = true) @RequestParam(value = "oiId") String oiId,
            @ApiParam(name = "addr", value = "地址", required = true) @RequestParam(value = "addr") String addr,
            @ApiParam(name = "pos", value = "经纬度", required = true) @RequestParam(value = "pos") String pos) {
        try {
            return Result.success(orderInfService.updateOrderInfDown(tiId, oiId, addr, pos, getToken()));
        } catch (Exception e) {
            return Result.error(e.getMessage(), 500100);
        }
    }

    /**
     * 删除任务信息表数据
     *
     * @return
     */
    @ApiOperation(value = "司机投诉订单接口", notes = "通过拒绝原因和任务信息拒绝接受任务", httpMethod = "POST")
    @PostMapping(value = "/complaint", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    @SSO
    public Result complaint(@RequestBody @Valid ComplaintDTO complaintDTO, BindingResult result) {
        if (result.hasErrors()) {
            return Result.error(CodeMsg.PARAMETER_ISNULL.getMessage(), 500101);
        }
        try {
            OrderInf orderInf = this.orderInfService.selectById(complaintDTO.getOiId());
            if (orderInf != null) {
                BeanUtil.copyProperties(complaintDTO, orderInf, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true).setIgnoreCase(true));
                orderInf.updateById();
                return Result.success("投诉成功!");
            }
            return Result.error("投诉订单不存在!", 100010);
        } catch (Exception e) {
            return Result.error(e.getMessage(), 500100);
        }
    }

    /**
     * 乘客下单
     *
     * @param orderInf
     * @param result
     * @return
     */
    @ApiOperation(value = "乘客下单", notes = "乘客下单", httpMethod = "POST")
    @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result add(@RequestBody @ApiParam(name = "orderInf ", value = "订单信息对象") OrderInf orderInf, BindingResult result
    ) {
        if (result.hasErrors()) {
            return Result.error(CodeMsg.PARAMETER_ISNULL.getMessage(), 500101);
        }
        /**写加悲观锁 防止并发下多次修改*/
        long stamp = stampedLock.writeLock();
        try {
            if (orderInf == null || orderInf.getOlId() == null || orderInf.getOlId().length() < 20 ||
                    orderInf.getOstId() == null || !(orderInf.getOstId().equals("0") || orderInf.getOstId().equals("1")) ||
                    orderInf.getOtId() == null || !(orderInf.getOtId().equals("CJ") || orderInf.getOtId().equals("JC")) ||
                    orderInf.getBasePrice() == null || orderInf.getBasePrice() < 1 ||
                    orderInf.getCiId() == null || orderInf.getCiId().trim().length() == 0 ||
                    orderInf.getCiTel() == null || orderInf.getCiTel().trim().length() < 10 ||
                    orderInf.getCiNum() == null || orderInf.getCiNum() < 1 ||
                    orderInf.getCiSendTime() == null ||
                    orderInf.getOiStartPoint() == null || orderInf.getOiStartPoint().trim().length() < 10 ||
                    orderInf.getOiEndPoint() == null || orderInf.getOiEndPoint().trim().length() < 10 ||
                    orderInf.getVptCode() == null || orderInf.getVptCode().trim().length() < 1 ||
                    orderInf.getOiDistance() == null
            ) {
                throw new RuntimeException("必填参数不全");
            }
            if (orderInf.getCiSendTime().compareTo(new Date()) <= 0) {
                throw new RuntimeException("预约时间必须大于当前时间");
            }
            String prams = JSONUtil.toJsonPrettyStr(orderInf);
            String resultTxt = HttpRequest.post(bgServerUrl + "gunsApi/auth/orderInf/customeradd").body(prams).execute().body();

            JSONObject jsonResult = JSON.parseObject(resultTxt);
            if (jsonResult.containsKey("code")) {
                if (jsonResult.getIntValue("code") == 200) {
                    return Result.success(jsonResult.getJSONObject("data"));
                } else {
                    return Result.error(jsonResult.getString("message"), 500100);
                }
            } else {
                return Result.error("网络异常", 500100);
            }
        } catch (Exception e) {
            return Result.error(e.getMessage(), 500100);
        }finally {
            /**释放写锁*/
            stampedLock.unlockWrite(stamp);
        }
    }

    /**
     * 乘客我的订单
     *
     * @param orderInf
     * @param pageNum
     * @param pageSize
     * @return
     */
    @ApiOperation(value = "乘客我的订单", notes = "乘客我的订单", httpMethod = "POST")
    @PostMapping(value = "/pageList", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result pageList(
            @RequestBody @ApiParam(name = "orderInf", value = "订单信息对象") OrderInf orderInf,
            @ApiParam(name = "pageNum", value = "当前页数", required = true) @RequestParam(value = "pageNum", required = true) Integer pageNum,
            @ApiParam(name = "pageSize", value = "每页显示条数", required = true) @RequestParam(value = "pageSize", required = true) Integer pageSize
    ) {
        try {
            Pager pager = new Pager();
            /**页码从1 开始*/
            pager.setPageNumber(pageNum);
            pager.setPageSize(pageSize);
            pager.setObj(orderInf);
            return Result.success(orderInfService.pageListOrderInf(pager, null));
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(e.getMessage(), 500100);
        }
    }

    /**
     * 乘客我的订单
     *
     * @param oiId
     * @return
     */
    @ApiOperation(value = "乘客我的订单", notes = "乘客我的订单", httpMethod = "POST")
    @PostMapping(value = "/getById", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result getById(
            @ApiParam(name = "oiId", value = "订单id", required = true) @RequestParam(value = "oiId", required = true) String oiId
    ) {
        try {
            return Result.success(orderInfService.getById(oiId));
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(e.getMessage(), 500100);
        }
    }

    /**
     * 乘客取消订单
     *
     * @param oiId
     * @return
     */
    @ApiOperation(value = "乘客取消订单", notes = "乘客下单", httpMethod = "POST")
    @PostMapping(value = "/cancelOrder", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result cancelOrder(
            @ApiParam(name = "oiId", value = "当前页数", required = true) @RequestParam(value = "oiId", required = true) String oiId
    ) {
        /**写加悲观锁 防止并发下多次修改*/
        long stamp = stampedLock.writeLock();
        try {
            OrderInf orderInf = orderInfService.getById(oiId);
            Map<String, String> map = new HashMap();
            //已取消  已下车  不可退款
            if (StringUtils.containsAny(orderInf.getCiState(), '2', '3')) {
                map.put("OK", "OK");
                return Result.success(map);
            } else{
                //调用远程接口取消订单
                Map paramMap = new LinkedHashMap();
                paramMap.put("oiId", oiId);
                paramMap.put("ope", "cancel");
                paramMap.put("orState","1");
                String resultTxt = HttpUtil.post(bgServerUrl + "gunsApi/auth/orderInf/customerOpeOrder", paramMap);
                JSONObject jsonResult = JSON.parseObject(resultTxt);
                if (jsonResult.containsKey("code")) {
                    if (jsonResult.getIntValue("code") == 200) {
                        map.put("OK", "OK");
                        return Result.success(map);
                    } else {
                        map.put("OK", "error");
                        map.put("msg", jsonResult.getString("message"));
                        return Result.success(map);
                    }
                } else {
                    return Result.error("网络异常", 500100);
                }
            }
        } catch (Exception e) {
            return Result.error(e.getMessage(), 500100);
        } finally {
            stampedLock.unlockWrite(stamp);
        }
    }

    @ApiOperation(value = "乘客支付回调接口", notes = "乘客支付回调接口", httpMethod = "POST")
    @PostMapping(value = "/pay", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result pay(@RequestBody PayVo vo, BindingResult result) {
        String message = "";
        if (result.hasErrors()) {
            return Result.error(CodeMsg.PARAMETER_ISNULL.getMessage(), 500101);
        }
        try {
            String json = JSONObject.toJSONString(vo);
            String oiid = vo.getOut_trade_no();
            log.debug("json对象:{}", json);
            OrderInf orderInf = orderInfService.getById(oiid);
            if (orderInf != null) {
                //调用远程接口取消订单
                Map paramMap = new LinkedHashMap();
                paramMap.put("oiId", oiid);
                paramMap.put("ope", "paySuc");
                String resultTxt = HttpUtil.post(bgServerUrl + "gunsApi/auth/orderInf/customerOpeOrder", paramMap);
                JSONObject jsonResult = JSON.parseObject(resultTxt);
                if (jsonResult.containsKey("code")) {
                    if (jsonResult.getIntValue("code") == 200) {
                        message = "订单修改状态成功！";
                    } else {
                        message = "订单修改状态失败!";
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(e.getMessage(), 500100);
        }
        return Result.success(message);
    }

    @ApiOperation(value = "乘客退单回调接口", notes = "乘客退单回调接口", httpMethod = "POST")
    @PostMapping(value = "/refund", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result refund(@RequestParam(value = "oiid", required = true) String oiid) {
        try {
            log.debug("oiid:" + oiid);
            OrderInf orderInf = orderInfService.getById(oiid);
            if (orderInf != null) {
                orderInf.setPayState("3");
                orderInf.updateById();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(e.getMessage(), 500100);
        }
        return Result.success("退款成功！");
    }

    private String getToken() {
        return getHttpServletRequest().getHeader("Authorization").substring(7);
    }
}
